#include "config.h"

#include "ms2sim.h"

static ecm_uint64	ts_advance = 1000000;	/* 1 sec */
static ecm_uint64	ts_arrival;

static msl_arrival_t	msl_arrival;
static msl_popularity_t	msl_popularity;

static ecm_uint64	total_n_arrivals;

static LIST_HEAD(arrival_infos);

typedef struct {
	ecm_uint64	ts;
	ecm_uint32	n_arrivals;
	struct list_head	list;
} arrival_info_t;

#ifdef MSM_DEBUG
static const char *
dbg_arrival_info(arrival_info_t *pinfo)
{
	static char	buf[256];

	if (pinfo == NULL)
		return "null";
	ecm_snprintf(buf, 256, "ts:%s n:%u", dbg_timestep(pinfo->ts), pinfo->n_arrivals);
	return buf;
}
#endif

static void
accept_request(arrival_info_t *pinfo)
{
	ecm_uint32	i;

	DBG(DBG_REQUEST, "new request: %d", pinfo->n_arrivals);

	if (is_stat_started)
		total_n_arrivals += pinfo->n_arrivals;

	for (i = 0; i < pinfo->n_arrivals; i++) {
		session_t	*session;
		ecm_uint32	mid;

		mid = msl_popularity_get(msl_popularity);
		session = create_session(pinfo->ts, mid);
		if (session != NULL)
			add_service_session(session);
	}
}

void
check_request_stats(void)
{
}

void
report_request_result(void)
{
	ecm_double	avg_arrival_rate;

	avg_arrival_rate = (1.0 * total_n_arrivals) / stat_duration;

	printlog("Avg Arrival Rate:            %.3lf/min\n", avg_arrival_rate * 60);
}

static void
fill_arrival_info(void)
{
	arrival_info_t	*pinfo;
	ecm_uint32	n_arrivals;

	ts_arrival += ts_advance;
	while ((n_arrivals = msl_arrival_get(msl_arrival)) == 0)
		ts_arrival += ts_advance;

	pinfo = (arrival_info_t *)ecm_malloc(sizeof(arrival_info_t));
	ECMASSERT(pinfo != NULL);

	pinfo->ts = ts_arrival;
	pinfo->n_arrivals = n_arrivals;
	list_add_tail(&pinfo->list, &arrival_infos);
}

ecm_uint64
probe_request_system(ecm_uint64 ts)
{
	arrival_info_t	*pinfo;

	if (ts_arrival == ts)
		ts_arrival = ts;

	if (list_empty(&arrival_infos)) {
		fill_arrival_info();
	}

	pinfo = list_entry(arrival_infos.next, arrival_info_t, list);
	return pinfo->ts;
}

void
schedule_request_system(ecm_uint64 ts)
{
	arrival_info_t	*pinfo;

	ECMASSERT(!list_empty(&arrival_infos));

	pinfo = list_entry(arrival_infos.next, arrival_info_t, list);

	DBG(DBG_REQUEST, "schedule: ts:%s, arrival_info:[%s]", dbg_timestep(ts), dbg_arrival_info(pinfo));

	accept_request(pinfo);

	list_del(&pinfo->list);
	ecm_free(pinfo);
}

ECMBOOL
init_request(void)
{
	msl_arrival = msl_arrival_create(arrival_rate, 0);
	msl_popularity = msl_popularity_create(n_medias, skew, 0);

	if (msl_arrival == NULL || msl_popularity == NULL) {
		msl_arrival_free(msl_arrival);
		msl_popularity_free(msl_popularity);

		ERR("init_client_request() failed");
		return ECM_FALSE;
	}

	return ECM_TRUE;
}
